﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using AO.Core;

namespace ZoneEngine.Functions
{
    abstract public class FunctionPrototype
    {
        /// <summary>
        /// Locks function targets and executes the function
        /// </summary>
        /// <param name="Self">Dynel (Character or NPC)</param>
        /// <param name="Caller">Caller of the function</param>
        /// <param name="Target">Target of the Function (Dynel or Statel)</param>
        /// <param name="Arguments">Function Arguments</param>
        /// <returns></returns>
        public abstract bool Execute(Dynel Self, Dynel Caller, Object Target, object[] Arguments);

        public int FunctionNumber = -1;
        public string FunctionName = "";

        public abstract int ReturnNumber();
        public abstract string ReturnName();

    }

    public class FunctionCollection
    {
        Dictionary<int, System.Type> Functions = new Dictionary<int, System.Type>();
        Assembly assembly;

        public bool ReadFunctions()
        {
            try
            {
                assembly = System.Reflection.Assembly.GetExecutingAssembly();

                foreach (Type t in assembly.GetTypes())
                {
                    if (t.IsClass)
                    {
                        if (t.Namespace == "ZoneEngine.Functions")
                        {
                            if ((t.Name != "FunctionPrototype") && (t.Name!="FunctionCollection"))
                            {
                                Functions.Add(((FunctionPrototype)assembly.CreateInstance(t.Namespace + "." + t.Name)).ReturnNumber(), t);
                            }
                        }
                    }
                }
            }
            catch
            {
                return false;
            }
            return true;
        }

        public bool CallFunction(int functionnum, Dynel self, Dynel Caller, object Target, object[] Arguments)
        {
            FunctionPrototype func = GetFunctionByNumber(functionnum);
            return func.Execute(self, Caller, Target, Arguments);
        }

        public FunctionPrototype GetFunctionByNumber(int functionnumber)
        {
            if (Functions.Keys.Contains(functionnumber))
            {
                return (FunctionPrototype)assembly.CreateInstance(Functions[functionnumber].Namespace + "." + Functions[functionnumber].Name);
            }
            return null;
        }

        public int NumberofRegisteredFunctions()
        {
            return Functions.Keys.Count;
        }
    }
}
